package org.cogaen.sound.xp;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

import org.cogaen.core.Core;
import org.cogaen.logging.LoggingService;
import org.cogaen.resource.ResourceHandle;
import org.cogaen.resource.ResourceManager;

public class SoundHandle extends ResourceHandle {

	private static final String LOGGING_SOURCE = ResourceManager.LOGGING_SOURCE;
	private Sound sound;
	private String filename;
	
	public SoundHandle(String name, String filename) {
		super(name);
		this.filename = filename;
	}

	@Override
	public boolean isLoaded() {
		return this.sound != null;
	}

	@Override
	public void load(Core core) {
		InputStream is = ResourceManager.getInstance(core).getStream(this.filename);
		
		if (is == null) {
			LoggingService logger = LoggingService.getInstance(core);
			logger.logWarning(LOGGING_SOURCE, "unable to locate '" + filename 
					+ "' referenced by sound resource '" + getName() + "'");
			
			return;
		}
		try {
			AudioInputStream ais = AudioSystem.getAudioInputStream(is);
			AudioFormat targetFormat = SoundManager.getInstance(core).getPlaybackFormat();
			
			try {
				if (true || !ais.getFormat().matches(targetFormat)){
					LoggingService logger = LoggingService.getInstance(core);
					logger.logInfo(LOGGING_SOURCE, "convert autio file '" 
							+ this.filename + "' referenced by '" + getName() + "'");				
					ais = AudioSystem.getAudioInputStream(targetFormat, ais);
				}
			} catch (Exception e) {
				LoggingService logger = LoggingService.getInstance(core);
				logger.logError(LOGGING_SOURCE, "unable to convert autio file format of '" 
						+ this.filename + "' referenced by '" + getName() + "': " + e.getMessage());				
			}

			int length = (int) (ais.getFrameLength() * ais.getFormat().getFrameSize());
			DataInputStream dis = new DataInputStream(ais);

			byte[] samples = new byte[length];
			dis.readFully(samples);
			dis.close();
			this.sound = new Sound(samples);
		} catch (UnsupportedAudioFileException e) {
			LoggingService logger = LoggingService.getInstance(core);
			logger.logError(LOGGING_SOURCE, "unsupported audio file format '" 
					+ this.filename + "' referenced by '" + getName() + "'");
		} catch (IOException e) {
			LoggingService logger = LoggingService.getInstance(core);
			logger.logError(LOGGING_SOURCE, "error while loading audio file '" 
					+ this.filename + "' referenced by '" + getName() + "'");
		}
	}

	@Override
	public void unload() {
		this.sound = null;
	}

	@Override
	public Object getResource() {
		return this.sound;
	}

}
